<?php
namespace StarCloud\Library;

use Phalcon\Di;

class FastRank
{
    /**
     * @var \Framework\DiServices\Redis
     */
    private $redis;
    private $key;
    private $order;

    public function __construct($key, $order)
    {
        $this->redis = Di::getDefault()->get('redis');
        $this->key = $key;
        $this->order = $order;
    }

    public static function instance($key, $order = 'DESC')
    {
        return new self($key, $order);
    }

    public function getRank($start, $stop)
    {
        if ($this->order == 'DESC') {
            return $this->redis->zRevRange($this->key, $start - 1, $stop - 1, true);
        } else {
            return $this->redis->zRange($this->key, $start - 1, $stop - 1, true);
        }
    }

    public function getMemberRank($rankLimit, $member) : int
    {
        if ($this->order == 'DESC') {
            $memberRank = $this->redis->zRevRank($this->key, $member);
        } else {
            $memberRank = $this->redis->zRank($this->key, $member);
        }

        if ($memberRank === false || $memberRank >= $rankLimit) {
            return 0;
        } else {
            return (int) $memberRank + 1;
        }
    }

    public function getMemberScore($member)
    {
        return $this->redis->zScore($this->key, $member);
    }

    public function addMemberToRank($score, $member)
    {
        if ($score < 0) {
            return;
        }

        if ($score == 0) {
            $this->remMemberFromRank($member);
        } else {
            $this->redis->zAdd($this->key, $score, $member);
        }
    }

    public function incrMemberScoreToRank($incrScore, $member)
    {
        $this->redis->zIncrBy($this->key, $incrScore, $member);
    }

    public function remMemberFromRank($member)
    {
        $this->redis->zRem($this->key, $member);
    }

    public function limitRank($rankLimit)
    {
        if ($this->order == 'DESC') {
            $this->redis->zRemRangeByRank($this->key, 0, -($rankLimit + 1));
        } else {
            $this->redis->zRemRangeByRank($this->key, $rankLimit + 1, -1);
        }
    }
}
